class ApplicationAccount < ActiveRecord::Base
  belongs_to :distributor
  has_many :bundles, :through => :bundle_variations
  has_and_belongs_to_many :bundle_variations
  
  validates_presence_of :name, :api_key, :distributor_id 
  validates_length_of       :name,    :within => 5..50
  validates_length_of       :description,    :within => 30..1000, :message => "Description is too short."
  
  validates_uniqueness_of :name, :api_key
  validates_format_of       :url, :with =>
          /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix, :message => "The URL format(http://domain.com) is invalid."
  before_validation_on_create :generate

  # before_destroy { |record| Person.destroy_all "firm_id = #{record.id}"   }
  # before_destroy { |record| record.status !=RefActionStatus::CANCELED }

  # ----- SCOPE
  named_scope :active, :conditions => ["status = ?", RefActionStatus::ACTIVE]
  # ----- End SCOPE
  
  #----- Act as FINITE STATE MACHINE -------------
  acts_as_state_machine :initial => :inactive, :column => :status

  # !!!!   for other special functions that
  # requires to change the status
  # use callback
  # state :inactive, :column => :status, :enter => :method1, .... read documentations

  # add updated_at     - change the date with any changing state
  
  state :inactive, :column => :status
  state :active, :column => :status
  
  # work for DEMO Architect
  # state :demo, :column => :status
      
  state :canceled, :column => :status

  event :activate do
    transitions :from => :inactive, :to => :active
  end

  event :deactivate do
    transitions :from => :active, :to => :inactive
  end
  
  event :cancel do
    transitions :from => :active, :to => :canceled
    transitions :from => :inactive, :to => :canceled
  end
  
  # reference of statuses for this model
  def self.statuses
    [RefActionStatus::ACTIVE, RefActionStatus::INACTIVE, RefActionStatus::CANCELED]
  end
  #-----------------------------------------------

  # !!!!! will add after subscription plan will be finished
  def destroy_or_canceled
    # if no client users destroy
    # else set canceled status
    
    if self.status == RefActionStatus::ACTIVE
      self.cancel!
    elsif self.status == RefActionStatus::CANCELED
      self.errors.add_to_base "The Application Account '#{self.id} #{self.name}' is in status #{RefActionStatus::CANCELED}!"
      return false
    else
      self.destroy
    end
    return true
  end

  
  #regenerate the API key
  def regenerate_apikey
    generate
    save(false)
  end

  private
  def generate
    record = true
    while record
      random = KeyGenerator.generate                                        
      record = ApplicationAccount.find(:first, :conditions => ["api_key = ?", random])
    end          
    self.api_key = random
  end

  class KeyGenerator
   require "digest/sha1"
   def self.generate(length = 30)
     Digest::SHA1.hexdigest(Time.now.to_s + rand(12341234).to_s)[1..length]
   end
  end
end